#! /usr/bin/python

#############################################################
# THIS FILE CONTAINS THE FUNCTIONS THAT HANDLE TIMMY-CHUNKS #
#############################################################
#
# Timmy Chunk Description:
# DICTIONARY holds:
#	* 'collision', 'object', 'background' (map tile layers)
#		* 2d array (string map tile data)
#	* 'dimmies'
#		* array of string data (each entry contains a line)
#
##############################################################

import re

# creates an empty TC of size r,c
def new(r, c):
	timmy_chunk = {'collision':[],'object':[],'background':[]}
	for layer in timmy_chunk.keys():
		for i in range(0,r):
			timmy_chunk[layer].append([])
			for j in range(0,c):
				timmy_chunk[layer][i].append('0')
	timmy_chunk['dimmies'] = []
	return timmy_chunk



# inserts a TC into another one at specified location
def insert(big_tc, little_tc, r, c):
	for i in range(0, len(little_tc['collision'])):
		for j in range(0, len(little_tc['collision'][i])):
			big_tc['collision'][r+i][c+j] = little_tc['collision'][i][j]
			big_tc['object'][r+i][c+j] = little_tc['object'][i][j]
			big_tc['background'][r+i][c+j] = little_tc['background'][i][j]
	#remove big_tc's overwritten dimmies
	big_tc = remove_dimmies(big_tc, r, c, len(little_tc['collision']), len(little_tc['collision'][0]))
	#now update little_tc's dimmies to fit in the big_tc
	for line in little_tc['dimmies']:
		for change in re.findall('{[0-9, ]+}', line):
			new_coord = translate_dimmy(change,r,c)
			line = line.replace(change, new_coord)
		big_tc['dimmies'].append(line)
	return big_tc

# changes a coordinate string into a translated one (eg. "{1,2,3,4}")
def translate_dimmy(c, row, col):
	c = c.strip('{}').split(',')
	#remember here that row and column are backwards in FLARE engine
	c[0] = str(int(c[0]) + col)
	c[1] = str(int(c[1]) + row)
	#recompile the coordinates
	new_c = '{'
	for v in c:
		new_c += v + ','
	new_c = new_c.strip(',') + '}'
	return new_c

# rotates a TC counter-clockwise a number of times equal to argument
def rotate(tc, n):
	#iterate 'n' times
	for num in range(0, n):
		#first save the dimmy info
		dimmyinfo = []
		for line in tc['dimmies']:
			dimmyinfo.append(line)
		#now rotate all of the layer info
		blank = new(len(tc['collision'][0]),len(tc['collision']))
		for i in range(0, len(tc['collision'])):
			for j in range(0, len(tc['collision'][i])):
				blank['collision'][len(blank['collision'])-1-j][i] = tc['collision'][i][j]
				blank['object'][len(blank['collision'])-1-j][i] = tc['object'][i][j]
				blank['background'][len(blank['collision'])-1-j][i] = tc['background'][i][j]
		tc = blank
		#now update all the dimmy position data
		for i in range(0,len(dimmyinfo)):
			line = dimmyinfo[i]
			new_change = ''
			for change in re.findall('{[0-9, ]+}', line):
				new_change = rotate_dimmy(change,tc)
				dimmyinfo[i] = dimmyinfo[i].replace(change, new_change)
		tc['dimmies'] = dimmyinfo
		#return it!
	return tc


# changes a coordinate string into a rotated one (eg. "{1,2,3,4}") TODO: clean up this subroutine
def rotate_dimmy(c, tc):
	c = c.strip('{}').split(',')
	#remember here that row and column are backwards in FLARE engine
	j = int(c[0])
	i = int(c[1])
	c[0] = str(i) #the column coordinate
	c[1] = str(len(tc['collision'])-1-j) #the row
	if len(c) == 3: #case = monster, so third argument is a face direction
		c[2] = int(c[2]) - 2
		if c[2] < 0: c[2] += 8
		c[2] = str(c[2])
	elif len(c) == 4: #case = effect, so third/fourth args are width and height
		w = int(c[2])
		c[2] = c[3]
		c[3] = str(w)
		#in this case the coordinate center must be adjusted by the new height to line up properly
		c[1] = str(int(c[1]) - (int(c[3])-1))
	#recompile the coordinates
	new_c = '{'
	for v in c:
		new_c += v + ','
	new_c = new_c.strip(',') + '}'
	return new_c



#removes all dimmy info in the selected range
def remove_dimmies(tc, r, c, w, h):
	dimmy_index = 0 #marks the start of the current dimmy
	for i in range(0, len(tc['dimmies'])):
		line = tc['dimmies'][i]
		hits = re.findall('{[0-9, ]+}', line)
		for hit in hits:
			if coordinate_in_range(hit, r, c, w, h):
				flag = 0
				tc['dimmies'][dimmy_index] = '#'
				for j in range(dimmy_index + 1, len(tc['dimmies'])):
					if flag == 0:
						if tc['dimmies'][j][0] == '[':
							flag = 1
						else:
							tc['dimmies'][j] = '#'
		if line[0] == '[': #marks the new dimmy
			dimmy_index = i
	return tc
	

# finds if the coordinate string is in the range defined
def coordinate_in_range(hit,r,c,w,h):
	hit = hit.strip('{}').split(',')
	#remember here that row and column are backwards in FLARE engine
	if ((int(hit[0]) >= c) and (int(hit[0]) < (c+w))) and ((int(hit[1]) >= r) and (int(hit[1]) < (r+h))):
		return True
	else:
		return False

# loads a timmy chunk of any size into the 'TC' format from file
def load(filename):
	f = open(filename,'r')
	lines = f.readlines()
	f.close()
	
	mode = '' # keeps track of what it's loading data into...
	data = {'dimmies':[]} # holds the moded data


	for line in lines:
		line = line.strip()
		if (len(line) != 0) and (line[0] != '#'): # skip comments and empty lines

			if (line[0] == '<'): # sets mode for lines like: <background>
				mode = line.strip('<>')
				data[mode] = []
			else: # load data into appropriate mode
				if mode == 'dimmies':
					data[mode].append(line)
				else: # area data
					data[mode].append(line.strip(',').split(','))

	return data
